package com.taysear.bus.util.vaadin;

import com.vaadin.data.util.BeanContainer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@SuppressWarnings("serial")
public class SmartBeanContainer<K, V> extends BeanContainer<K, V> {

  public SmartBeanContainer(Class<? super V> type) {
    super(type);
  }
  
  @Override
  public List<K> getAllItemIds() {
	  return super.getAllItemIds();
  }

/**
   * Move (up or down) a set of items.
   * @param toMove The IDs of rows to be moved.
   * @param offset The offset to be moved: -1 = 1 row up, +5 = 5 rows down and 
   *   so on.
   */
  public void move(Set<Object> toMove, int offset) {
    //System.out.println("move>>>" + offset);
    List<K> ids = getAllItemIds();
    List<K> pending = new ArrayList<K>(ids);
    Object[] newIds = new Object[ids.size()];
    for (Object id: toMove) {
      int index = indexOfId(id) + offset;
      if (index >= 0 && index < ids.size()) {
        newIds[index] = id;
        pending.remove((K)id);
      }
    }
    int i = 0;
    for (K id: pending) {
    	while (newIds[i] != null)
    		i++;
      newIds[i++] = id;
    }
    ids.clear();
    for (Object id: newIds)
      ids.add((K)id);
    if (isFiltered()) {
      filterAll();
    } else {
      fireItemSetChange();
    }
  }

  /**
   * Compute maximum move span. This can be used to enable and disable move
   * buttons and to compute the offset needed to move first selected item
   * to top or last selected item to bottom.
   * @param toMove toMove The IDs of rows to be moved.
   * @return A 2-elements array indicating the maximum negative and positive
   *   move without exceeding table boundaries. Foe example [-5, +2] indicates 
   */
  public int[] getMoveSpans(Set<Object> toMove) {
    int l = getAllItemIds().size();
    if (l == 0 || toMove.isEmpty())
      return new int[] {0, 0};
    int first = l - 1;
    int last = 0;
    for (Object o: toMove) {
      int i = indexOfId(o);
      first = Math.min(first , i);
      last = Math.max(last , i);
    }
    return new int[] {-first, l - 1 - last};
  }
}
